Imports System.Drawing
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary

Imports JS.Herramientas.Seguridad

Imports JS.Nativo.WinFormUI.Socios
Imports JS.Nativo.WinFormUI.LocalizacionGeografica

Public Class frmArbolFormularios

    Private Const cNODOACCESOSDIRECTOS = "ACCESOSDIRECTOS"
    Private Const cSUFIJOACCESODIRECTO = ".accesodirecto"

    Private Const cCARPETA = "Carpeta"
    Private Const cFORMULARIO = "Formulario"

    Private mInstanciasFormularios As New Dictionary(Of Type, Form)

    Protected Overrides Function Autorizado() As Boolean
        Return True
    End Function

    Private Sub frmArbolFormularios_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        CargarListaImagenes()
        CargarNodos()
        CargarAccesosDirectos()
    End Sub

    Private Sub CargarListaImagenes()
        For Each clave As String In imgListaIconos.Images.Keys
            imgListaIconos.Images.Add(clave + cSUFIJOACCESODIRECTO, ObtenerIconoAccesoDirecto(imgListaIconos.Images(clave)))
        Next
    End Sub

    Private Sub CargarNodos()
        Dim accesos As New TreeNode("Accesos directos")
        accesos.ImageKey = cCARPETA
        accesos.Name = cNODOACCESOSDIRECTOS
        treFormularios.Nodes.Add(accesos)

        Dim listaNodos As New SortedList(Of Integer, NodoArbol)()
        For Each formulario As String In Formularios.FormulariosAutorizados
            Dim infoNodo As NodoArbol = Formularios.ObtenerNodo(formulario)
            listaNodos.Add(infoNodo.Orden, infoNodo)
        Next
        Dim listaTreeNodes As New Dictionary(Of String, TreeNode)()
        CargarNodoIntermedio(Formularios.ObtenerNodo(Formularios.Arbol.Nombre), listaTreeNodes)
        For Each infoNodo As KeyValuePair(Of Integer, NodoArbol) In listaNodos
            CargarNodoHoja(infoNodo.Value, listaTreeNodes)
        Next

        treFormularios.Nodes.Add(listaTreeNodes(Formularios.Arbol.Nombre))
    End Sub

    Private Sub CargarNodoHoja(ByVal pInfoNodo As NodoArbol, ByVal pListaTreeNodes As Dictionary(Of String, TreeNode))
        If pInfoNodo Is Nothing Then
            Return
        End If
        'Carga el nodo padre si no lo encuentra
        If Not pListaTreeNodes.ContainsKey(pInfoNodo.NombrePadre) Then
            If Not CargarNodoIntermedio(Formularios.ObtenerNodo(pInfoNodo.NombrePadre), pListaTreeNodes) Then
                Return
            End If
        End If
        Dim nodo As New TreeNode(pInfoNodo.Texto)
        nodo.Name = pInfoNodo.Nombre
        nodo.Tag = pInfoNodo.Formulario
        nodo.ImageKey = cFORMULARIO
        nodo.SelectedImageKey = cFORMULARIO
        pListaTreeNodes(pInfoNodo.NombrePadre).Nodes.Add(nodo)
        pListaTreeNodes.Add(pInfoNodo.Nombre, nodo)
    End Sub

    Private Function CargarNodoIntermedio(ByVal pInfoNodo As NodoArbol, ByVal pListaTreeNodes As Dictionary(Of String, TreeNode)) As Boolean
        If pInfoNodo Is Nothing Then
            Return False
        End If
        'Carga el nodo padre si no lo encuentra
        If Not String.IsNullOrEmpty(pInfoNodo.NombrePadre) AndAlso Not pListaTreeNodes.ContainsKey(pInfoNodo.NombrePadre) Then
            If Not CargarNodoIntermedio(Formularios.ObtenerNodo(pInfoNodo.NombrePadre), pListaTreeNodes) Then
                Return False
            End If
        End If
        Dim nodo As New TreeNode(pInfoNodo.Texto)
        nodo.Name = pInfoNodo.Nombre
        nodo.ImageKey = cCARPETA
        nodo.SelectedImageKey = cCARPETA
        If Not String.IsNullOrEmpty(pInfoNodo.NombrePadre) Then
            pListaTreeNodes(pInfoNodo.NombrePadre).Nodes.Add(nodo)
        End If
        pListaTreeNodes.Add(pInfoNodo.Nombre, nodo)
        Return True
    End Function

    Private Sub GuardarAccesosDirectos()
        Dim serializer As New BinaryFormatter()
        Dim accesos As New List(Of ArrayList)()
        Dim accesosStream As New MemoryStream()
        Try
            For Each nodo As TreeNode In treFormularios.Nodes(cNODOACCESOSDIRECTOS).Nodes
                Dim acceso As New ArrayList()
                acceso.Add(nodo.Name)
                acceso.Add(nodo.Text)
                acceso.Add(nodo.Tag)
                acceso.Add(nodo.ImageKey)
                acceso.Add(nodo.SelectedImageKey)
                accesos.Add(acceso)
            Next
            serializer.Serialize(accesosStream, accesos)
        Finally
            My.Settings.AccesosDirectosFormularios = Convert.ToBase64String(accesosStream.ToArray())
        End Try
    End Sub

    Private Sub CargarAccesosDirectos()
        Try
            If Not String.IsNullOrEmpty(My.Settings.AccesosDirectosFormularios) Then
                Dim serializer As New BinaryFormatter()
                Dim accesos As New List(Of ArrayList)()

                accesos = serializer.Deserialize(New MemoryStream(Convert.FromBase64String(My.Settings.AccesosDirectosFormularios)))
                Dim nodo As TreeNode
                For Each acceso As ArrayList In accesos
                    If Formularios.FormulariosAutorizados.Contains(CType(acceso(2), DatosFormulario).Nombre) Then
                        nodo = New TreeNode()
                        nodo.Name = acceso(0)
                        nodo.Text = acceso(1)
                        nodo.Tag = acceso(2)
                        nodo.ImageKey = acceso(3)
                        nodo.SelectedImageKey = acceso(4)
                        treFormularios.Nodes(cNODOACCESOSDIRECTOS).Nodes.Add(nodo)
                    End If
                Next
            End If
            treFormularios.Nodes(cNODOACCESOSDIRECTOS).ExpandAll()
        Catch ex As Exception
            Exit Sub
        End Try
    End Sub

    Private Sub treFormularios_NodeMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles treFormularios.NodeMouseClick
        If e.Button = Windows.Forms.MouseButtons.Left Then
            If e.Node.Tag IsNot Nothing Then
                MostrarFormulario(e.Node.Tag)
            End If
        End If
        treFormularios.SelectedNode = e.Node
    End Sub

    Private Sub treFormularios_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles treFormularios.KeyPress
        If e.KeyChar = ControlChars.Cr Then
            If treFormularios.SelectedNode IsNot Nothing AndAlso treFormularios.SelectedNode.Tag IsNot Nothing Then
                MostrarFormulario(treFormularios.SelectedNode.Tag)
            End If
        End If
    End Sub

    Private Sub cmnuAccesosDirectosCrearAccesoDirecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmnuAccesosDirectosCrearAccesoDirecto.Click
        If treFormularios.SelectedNode IsNot Nothing AndAlso treFormularios.SelectedNode.Tag IsNot Nothing AndAlso Not EsAccesoDirecto(treFormularios.SelectedNode) Then
            Dim frmAcceso As New frmAccesoDirecto()
            frmAcceso.Nombre = treFormularios.SelectedNode.Text
            If frmAcceso.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim acceso As New TreeNode()
                acceso.Name = treFormularios.SelectedNode.Name + cSUFIJOACCESODIRECTO
                acceso.Text = frmAcceso.Nombre
                acceso.Tag = treFormularios.SelectedNode.Tag
                acceso.ImageKey = treFormularios.SelectedNode.ImageKey + cSUFIJOACCESODIRECTO
                acceso.SelectedImageKey = treFormularios.SelectedNode.SelectedImageKey + cSUFIJOACCESODIRECTO
                treFormularios.Nodes.Item(cNODOACCESOSDIRECTOS).Nodes.Add(acceso)
            End If
        End If
    End Sub

    Private Sub cmnuAccesosDirectos_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles cmnuAccesosDirectos.Opening
        If Not (treFormularios.SelectedNode IsNot Nothing AndAlso treFormularios.SelectedNode.Tag IsNot Nothing) Then
            e.Cancel = True
        ElseIf EsAccesoDirecto(treFormularios.SelectedNode) Then
            cmnuAccesosDirectosBorrarAccesoDirecto.Enabled = True
            cmnuAccesosDirectosCrearAccesoDirecto.Enabled = False
            cmnuAccesosDirectosCambiarNombre.Enabled = True
        Else
            cmnuAccesosDirectosBorrarAccesoDirecto.Enabled = False
            cmnuAccesosDirectosCrearAccesoDirecto.Enabled = True
            cmnuAccesosDirectosCambiarNombre.Enabled = False
        End If
    End Sub

    Private Function EsAccesoDirecto(ByVal pNodo As TreeNode) As Boolean
        If pNodo.Parent Is Nothing Then
            Return pNodo.Equals(treFormularios.Nodes(cNODOACCESOSDIRECTOS))
        Else
            Return EsAccesoDirecto(pNodo.Parent)
        End If
    End Function

    Private Sub cmnuAccesosDirectosBorrarAccesoDirecto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmnuAccesosDirectosBorrarAccesoDirecto.Click
        If treFormularios.SelectedNode IsNot Nothing AndAlso treFormularios.SelectedNode.Tag IsNot Nothing AndAlso EsAccesoDirecto(treFormularios.SelectedNode) Then
            treFormularios.Nodes.Remove(treFormularios.SelectedNode)
        End If
    End Sub

    Private Sub cmnuAccesosDirectosCambiarNombre_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmnuAccesosDirectosCambiarNombre.Click
        If treFormularios.SelectedNode IsNot Nothing AndAlso treFormularios.SelectedNode.Tag IsNot Nothing AndAlso EsAccesoDirecto(treFormularios.SelectedNode) Then
            Dim frmAcceso As New frmAccesoDirecto()
            frmAcceso.Nombre = treFormularios.SelectedNode.Text
            If frmAcceso.ShowDialog() = Windows.Forms.DialogResult.OK Then
                treFormularios.SelectedNode.Text = frmAcceso.Nombre
            End If
        End If
    End Sub

    Private Sub MostrarFormulario(ByVal pFormulario As DatosFormulario)
        Dim formulario As Form
        Dim instanciar As Boolean = False
        If mInstanciasFormularios.ContainsKey(pFormulario.Formulario) Then
            formulario = mInstanciasFormularios(pFormulario.Formulario)
            If formulario Is Nothing OrElse formulario.IsDisposed Then
                instanciar = True
            End If
        Else
            instanciar = True
        End If
        If instanciar Then
            formulario = Activator.CreateInstance(pFormulario.Formulario)
            formulario.MdiParent = Me.MdiParent
            mInstanciasFormularios(pFormulario.Formulario) = formulario
            formulario.Show()
        Else
            formulario.BringToFront()
        End If
    End Sub

    Private Function ObtenerIconoAccesoDirecto(ByVal pImagen As Image) As Image
        Dim grafico As Graphics
        Dim imagen As New Bitmap(pImagen.Width, pImagen.Height)
        grafico = Graphics.FromImage(imagen)
        grafico.DrawImage(pImagen, 0, 0)
        grafico.DrawImage(My.Resources.IconoAccesoDirecto, 0, imagen.Height - My.Resources.IconoAccesoDirecto.Height)
        grafico.Flush()
        grafico.Dispose()
        Return imagen
    End Function

    Private Sub frmArbolFormularios_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
        GuardarAccesosDirectos()
    End Sub

End Class